package scatter.moment.rest.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.Assert;
import scatter.common.pojo.form.BasePageQueryForm;
import scatter.moment.pojo.form.MomentAvailablePageQueryForm;
import scatter.moment.pojo.param.MomentStarAddStarParam;
import scatter.moment.pojo.param.MomentCancelStarParam;
import scatter.moment.pojo.po.Moment;
import scatter.moment.pojo.po.MomentStar;
import scatter.moment.rest.mapper.MomentStarMapper;
import scatter.moment.rest.mapstruct.MomentStarMapStruct;
import scatter.moment.rest.service.IMomentService;
import scatter.moment.rest.service.IMomentStarService;
import scatter.common.rest.service.IBaseAddUpdateQueryFormServiceImpl;
import org.springframework.stereotype.Service;
import scatter.moment.pojo.form.MomentStarAddForm;
import scatter.moment.pojo.form.MomentStarUpdateForm;
import scatter.moment.pojo.form.MomentStarPageQueryForm;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * <p>
 * 时刻动态点赞表 服务实现类
 * </p>
 *
 * @author yw
 * @since 2021-10-26
 */
@Slf4j
@Service
@Transactional
public class MomentStarServiceImpl extends IBaseAddUpdateQueryFormServiceImpl<MomentStarMapper, MomentStar, MomentStarAddForm, MomentStarUpdateForm, MomentStarPageQueryForm> implements IMomentStarService {

    @Qualifier("commonDbTaskExecutor")
    @Autowired
    private ExecutorService executorService;
    @Lazy
    @Autowired
    private IMomentService iMomentService;


    @Override
    public void preAdd(MomentStarAddForm addForm,MomentStar po) {
        super.preAdd(addForm,po);

    }

    @Override
    public void preUpdate(MomentStarUpdateForm updateForm,MomentStar po) {
        super.preUpdate(updateForm,po);

    }


    /**
     * 异步处理添加，该方法永远返回true
     * @param addStartParam
     * @return
     */
    @Override
    public MomentStar addStar(MomentStarAddStarParam addStartParam) {
        MomentStar momentStar = MomentStarMapStruct.INSTANCE.addStartParamToPo(addStartParam);
        momentStar.setTimeAt(LocalDateTime.now());
        log.info("开始添加一个点赞,momentId={},userId={}",addStartParam.getMomentId(),addStartParam.getOwnerUserId());
        save(momentStar);
        // 添加成功后，点赞数加 1
        iMomentService.plusForColumnById(addStartParam.getMomentId(), Moment::getStarCount,1);
        log.info("添加一个点赞结束,momentId={},userId={}",addStartParam.getMomentId(),addStartParam.getOwnerUserId());
        return momentStar;
    }

    /**
     * 异步处理取消，该方法永远返回 true
     * @param cancelStarParam
     * @return
     */
    @Override
    public boolean cancelStar(MomentCancelStarParam cancelStarParam) {
        executorService.execute(()->{
            log.info("开始取消点赞,momentId={},userId={}",cancelStarParam.getMomentId(),cancelStarParam.getOwnerUserId());
            boolean remove = remove(Wrappers.<MomentStar>lambdaQuery()
                    .eq(MomentStar::getMomentId, cancelStarParam.getMomentId())
                    .eq(MomentStar::getOwnerUserId, cancelStarParam.getOwnerUserId())
            );
            if (remove) {
                // 取消成功后，点赞数减 1
                iMomentService.plusForColumnById(cancelStarParam.getMomentId(), Moment::getStarCount,-1);
            }else {
                log.error("取消点赞失败，因删除点赞数据返回false，这将会导致对应的 时刻动态数据 点赞数不支减1");
            }
            log.info("取消点赞结束,momentId={},userId={}",cancelStarParam.getMomentId(),cancelStarParam.getOwnerUserId());

        });
        return true;
    }

    @Override
    public Map<String, Page<MomentStar>> listLatestStarForPerMoment(List<String> momentIds, Integer count) {
        Assert.notEmpty(momentIds,"momentIds 不能为空");
        Assert.notNull(count,"count 不能为空");


        Map<String,Page<MomentStar>> result = new HashMap<>();

        CompletableFuture[] completableFutures = momentIds.stream().map(momentId -> CompletableFuture.supplyAsync(() -> {
            // 我嚓，这个 page 不能提出来，否则得到的数据会是一样的
            Page page = convertPage(new BasePageQueryForm().setCurrent(1L).setSize(Integer.toUnsignedLong(count)));
            page.setSearchCount(false);
            Page page1 = page(page, Wrappers.<MomentStar>lambdaQuery().eq(MomentStar::getMomentId, momentId).orderByDesc(MomentStar::getTimeAt));
            return page1;
        }, executorService).whenComplete((r,e)->{result.put(momentId, (Page<MomentStar>)r);})).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(completableFutures).join();
        return result;
    }

}
